<?php


namespace App\Extensions\Grid\Exporters;


use Encore\Admin\Grid\Exporters\AbstractExporter;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;

abstract class ExcelExporter extends AbstractExporter implements FromQuery, WithHeadings, WithMapping
{
    use Exportable;

    /**
     * @var string
     */
    protected $fileName;

    protected $extension = 'csv';

    protected $content_type = [
        'csv' => 'text/csv;charset=UTF-8',
        'xls' => 'application/vnd.ms-excel;charset=UTF-8',
        'xlsx' => 'application/vnd.ms-excel;charset=UTF-8',
    ];

    /**
     * @var array
     */
    protected $headings = [];

    /**
     * @var array
     */
    protected $columns = [];

    /**
     * @return array
     */
    public function headings(): array
    {
        return $this->headings;
    }

    /**
     * 筛选无效bug $this->grid->applyQuery();
     * 自定义 export后未调用
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
     */
    public function query()
    {
        //筛选无效bug
        $this->grid->applyQuery();

        if (!empty($this->columns)) {
            $columns = $this->columns;

            $eagerLoads = array_keys($this->getQuery()->getEagerLoads());

            $columns = collect($columns)->reject(function ($column) use ($eagerLoads) {
                return Str::contains($column, '.') || in_array($column, $eagerLoads);
            });

            return $this->getQuery()->select($columns->toArray());
        }

        return $this->getQuery();
    }

    protected function getHeaders()
    {
        $filename = $this->getFileName();

        return [
            'Content-Encoding' => 'UTF-8',
            'Content-Type' => $this->getContentType(),
            //'Cache-Control' => 'max-age=0;',
            'Content-Disposition' => "attachment;filename=\"{$filename}.{$this->getExtension()}\"",
        ];
    }

    protected function getContentType()
    {
        if (!isset($this->content_type[$this->extension])) {
            $this->extension = 'csv';
        }
        return data_get($this->content_type, $this->extension);
    }

    protected function getExtension()
    {
        if (!isset($this->content_type[$this->extension])) {
            $this->extension = 'csv';
        }
        return $this->extension;
    }

    /**
     * 自定义为 下载流 分批查询数据库 防止下载过大页面报错
     * {@inheritdoc}
     */
    public function export()
    {
        $response = function () {
            $handle = fopen('php://output', 'w');

            //导出的CSV文件是无BOM编码UTF-8，而我们通常使用UTF-8编码格式都是有BOM的。所以添加BOM于CSV中
            fwrite($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));

            fputcsv($handle, $this->headings());

            $this->chunk(function ($collection) use ($handle) {
                foreach ($collection as $row) {
                    fputcsv($handle, $this->map($row));
                }
            });
            fclose($handle);
        };

        response()->stream($response, 200, $this->getHeaders())->send();

        exit;
    }

    /**
     * @return string
     */
    public function getFileName(): string
    {
        return $this->fileName;
    }

}
